/**
 * @file apiclient.cpp
 * @brief API客户端类实现文件
 *
 * 实现与后端API服务器通信的所有功能，包括：
 * - RESTful API调用的具体实现
 * - JWT令牌的自动管理和刷新
 * - 网络错误处理和重试机制
 * - 请求响应的解析和处理
 */

#include "../include/apiclient.h"
#include "../include/config.h"
#include <QUrlQuery>            // URL查询参数处理
#include <QJsonParseError>      // JSON解析错误处理
#include <QDebug>               // 调试输出
#include <QApplication>         // 应用程序信息

/**
 * @brief ApiClient构造函数
 * @param baseUrl API服务器的基础URL
 * @param parent 父对象指针
 *
 * 初始化API客户端的所有组件：
 * 1. 创建网络访问管理器
 * 2. 设置基础URL和配置参数
 * 3. 从本地存储加载保存的令牌
 */
ApiClient::ApiClient(const QString &baseUrl, QObject *parent)
    : QObject(parent)
    , m_networkManager(new QNetworkAccessManager(this))    // 创建网络管理器
    , m_baseUrl(baseUrl)                                    // 设置API基础URL
    , m_settings(new QSettings(this))                       // 创建设置存储对象
    , m_timeout(Config::getRequestTimeout())                // 从配置获取超时时间
    , m_retryCount(Config::getMaxRetries())                 // 从配置获取重试次数
{
    // === 初始化阶段 ===
    loadTokens();   // 从本地存储加载保存的认证令牌
}

/**
 * @brief 发送GET请求
 * @param endpoint API端点路径
 * @param params 查询参数（可选）
 *
 * 发送异步GET请求的完整流程：
 * 1. 构建完整的请求URL
 * 2. 处理查询参数（转换为URL查询字符串）
 * 3. 创建包含认证信息的请求对象
 * 4. 发送请求并设置超时控制
 * 5. 连接响应处理槽函数
 */
void ApiClient::get(const QString &endpoint, const QJsonObject &params)
{
    // === 构建请求URL ===
    QUrl url(m_baseUrl + endpoint);

    // === 处理查询参数 ===
    // 如果有查询参数，将JSON对象转换为URL查询字符串
    /* 示例转换过程：
     * 输入JSON对象：
     * {
     *   "gameType": "snake",
     *   "region": "asia",
     *   "limit": 50,
     *   "page": 1
     * }
     *
     * 转换后的URL查询字符串：
     * "gameType=snake&region=asia&limit=50&page=1"
     *
     * 最终完整URL：
     * "http://localhost:8008/api/v1/games/servers?gameType=snake&region=asia&limit=50&page=1"
     */
    if (!params.isEmpty()) {
        QUrlQuery query;
        for (auto it = params.begin(); it != params.end(); ++it) {
            // 将每个参数添加到查询字符串中
            // 例如：key="gameType", value="snake" -> "gameType=snake"
            query.addQueryItem(it.key(), it.value().toString());
        }
        url.setQuery(query);    // 设置URL的查询部分
    }

    // === 创建网络请求 ===
    QNetworkRequest request = createRequest(endpoint);
    request.setUrl(url);    // 设置完整的请求URL

    // === 发送GET请求 ===
    QNetworkReply *reply = m_networkManager->get(request);

    // === 设置请求属性 ===
    // 保存请求信息，用于错误处理和重试
    reply->setProperty("endpoint", endpoint);
    reply->setProperty("method", "GET");

    // === 设置超时控制 ===
    // 使用单次定时器实现请求超时控制
    QTimer::singleShot(m_timeout, reply, [reply]() {
        if (reply->isRunning()) {
            reply->abort();     // 超时后取消请求
        }
    });

    // === 连接响应处理 ===
    connect(reply, &QNetworkReply::finished, this, &ApiClient::onReplyFinished);
}

/**
 * @brief 发送POST请求
 * @param endpoint API端点路径
 * @param data 请求体数据（JSON格式）
 *
 * 发送异步POST请求的完整流程：
 * 1. 创建包含认证信息的请求对象
 * 2. 将JSON数据序列化为字节数组
 * 3. 发送POST请求
 * 4. 设置请求属性和超时控制
 * 5. 连接响应处理槽函数
 */
void ApiClient::post(const QString &endpoint, const QJsonObject &data)
{
    // === 创建网络请求 ===
    QNetworkRequest request = createRequest(endpoint);

    // === 序列化请求数据 ===
    // 将JSON对象转换为JSON文档，再转换为字节数组
    /* 示例转换过程：
     * 输入JSON对象（用户登录）：
     * {
     *   "username": "player123",
     *   "password": "securePassword",
     *   "rememberMe": true
     * }
     *
     * 转换后的JSON字符串（QByteArray）：
     * "{\"username\":\"player123\",\"password\":\"securePassword\",\"rememberMe\":true}"
     *
     * HTTP请求体内容：
     * Content-Type: application/json
     * Content-Length: 75
     *
     * {"username":"player123","password":"securePassword","rememberMe":true}
     */
    QJsonDocument doc(data);
    QByteArray jsonData = doc.toJson();  // 转换为紧凑的JSON字节数组

    // === 发送POST请求 ===
    QNetworkReply *reply = m_networkManager->post(request, jsonData);

    // === 设置请求属性 ===
    // 保存请求信息，用于错误处理和重试
    reply->setProperty("endpoint", endpoint);
    reply->setProperty("method", "POST");
    reply->setProperty("data", QVariant::fromValue(data));  // 保存原始数据用于重试

    // === 设置超时控制 ===
    QTimer::singleShot(m_timeout, reply, [reply]() {
        if (reply->isRunning()) {
            reply->abort();     // 超时后取消请求
        }
    });

    // === 连接响应处理 ===
    connect(reply, &QNetworkReply::finished, this, &ApiClient::onReplyFinished);
}

/**
 * @brief 发送PUT请求
 * @param endpoint API端点路径
 * @param data 请求体数据（JSON格式）
 *
 * 发送异步PUT请求，通常用于更新资源：
 * 1. 创建包含认证信息的请求对象
 * 2. 将JSON数据序列化为字节数组
 * 3. 发送PUT请求
 * 4. 设置请求属性和超时控制
 */
void ApiClient::put(const QString &endpoint, const QJsonObject &data)
{
    // === 创建网络请求 ===
    QNetworkRequest request = createRequest(endpoint);

    // === 序列化请求数据 ===
    QJsonDocument doc(data);
    QByteArray jsonData = doc.toJson();

    // === 发送PUT请求 ===
    QNetworkReply *reply = m_networkManager->put(request, jsonData);

    // === 设置请求属性 ===
    reply->setProperty("endpoint", endpoint);
    reply->setProperty("method", "PUT");
    reply->setProperty("data", QVariant::fromValue(data));  // 保存数据用于重试

    // === 设置超时控制 ===
    QTimer::singleShot(m_timeout, reply, [reply]() {
        if (reply->isRunning()) {
            reply->abort();
        }
    });

    // === 连接响应处理 ===
    connect(reply, &QNetworkReply::finished, this, &ApiClient::onReplyFinished);
}

/**
 * @brief 发送DELETE请求
 * @param endpoint API端点路径
 *
 * 发送异步DELETE请求，用于删除资源：
 * 1. 创建包含认证信息的请求对象
 * 2. 发送DELETE请求（无请求体）
 * 3. 设置请求属性和超时控制
 */
void ApiClient::del(const QString &endpoint)
{
    // === 创建网络请求 ===
    QNetworkRequest request = createRequest(endpoint);

    // === 发送DELETE请求 ===
    QNetworkReply *reply = m_networkManager->deleteResource(request);

    // === 设置请求属性 ===
    reply->setProperty("endpoint", endpoint);
    reply->setProperty("method", "DELETE");
    // DELETE请求通常不需要请求体数据

    // === 设置超时控制 ===
    QTimer::singleShot(m_timeout, reply, [reply]() {
        if (reply->isRunning()) {
            reply->abort();
        }
    });

    // === 连接响应处理 ===
    connect(reply, &QNetworkReply::finished, this, &ApiClient::onReplyFinished);
}

/**
 * @brief 创建网络请求对象
 * @param endpoint API端点路径
 * @return 配置完整的网络请求对象
 *
 * 创建包含所有必要头信息的网络请求：
 * 1. 设置完整的请求URL
 * 2. 设置内容类型为JSON
 * 3. 设置用户代理信息
 * 4. 添加JWT认证头（如果已认证）
 */
QNetworkRequest ApiClient::createRequest(const QString &endpoint)
{
    // === 创建基础请求对象 ===
    QNetworkRequest request;
    request.setUrl(QUrl(m_baseUrl + endpoint));     // 设置完整的请求URL

    // === 设置标准HTTP头 ===
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");

    // === 设置用户代理 ===
    // 格式：应用名称/版本号，用于服务器端统计和识别
    /* 示例用户代理字符串：
     * 输入：Config::getAppName() = "QtGameClient", Config::getAppVersion() = "1.0.0"
     * 输出：User-Agent: "QtGameClient/1.0.0"
     */
    request.setHeader(QNetworkRequest::UserAgentHeader,
                     QString("%1/%2").arg(Config::getAppName(), Config::getAppVersion()));

    // === 添加认证头 ===
    // 如果有访问令牌，添加Bearer认证头
    qDebug() << "ApiClient: 创建请求 -" << endpoint;
    qDebug() << "  访问令牌长度:" << m_accessToken.length();
    qDebug() << "  访问令牌前缀:" << (m_accessToken.length() > 20 ? m_accessToken.left(20) + "..." : m_accessToken);

    if (!m_accessToken.isEmpty()) {
        QString authHeader = "Bearer " + m_accessToken;
        request.setRawHeader("Authorization", authHeader.toUtf8());
        qDebug() << "  ✅ Authorization头已设置:" << authHeader.left(30) + "...";
    } else {
        qWarning() << "  ❌ 访问令牌为空，未设置Authorization头";
    }

    return request;
}

/**
 * @brief 网络请求完成槽函数
 *
 * 处理所有网络请求的响应，包括：
 * 1. 检查响应的有效性
 * 2. 处理401认证错误（自动刷新令牌）
 * 3. 将成功的响应传递给响应处理器
 * 4. 清理网络响应对象
 */
void ApiClient::onReplyFinished()
{
    // === 获取响应对象 ===
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    if (!reply) return;     // 安全检查

    // === 获取请求信息 ===
    QString endpoint = reply->property("endpoint").toString();

    // === 处理401认证错误 ===
    // 如果收到401错误且有刷新令牌，尝试自动刷新访问令牌
    if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 401
        && !m_refreshToken.isEmpty() && endpoint != "/api/v1/auth/refresh") {

        // === 保存请求信息以便重试 ===
        PendingRequest pendingRequest;
        pendingRequest.endpoint = endpoint;
        pendingRequest.method = reply->property("method").toString();
        pendingRequest.data = reply->property("data").value<QJsonObject>();
        pendingRequest.retryCount = 0;
        m_pendingRequests.append(pendingRequest);   // 添加到待重试队列

        // === 清理当前响应并刷新令牌 ===
        reply->deleteLater();
        refreshAccessToken();   // 异步刷新访问令牌
        return;
    }

    // === 处理正常响应 ===
    handleResponse(reply, endpoint);
    reply->deleteLater();   // 清理响应对象
}

/**
 * @brief 处理网络响应
 * @param reply 网络响应对象
 * @param endpoint API端点路径
 *
 * 解析响应数据并发出requestFinished信号
 */
void ApiClient::handleResponse(QNetworkReply *reply, const QString &endpoint)
{
    // === 解析响应数据 ===
    ApiResponse response = parseResponse(reply);

    // === 发出完成信号 ===
    emit requestFinished(endpoint, response);
}

/**
 * @brief 解析API响应数据
 * @param reply 网络响应对象
 * @return 解析后的API响应结构
 *
 * 将网络响应解析为标准的ApiResponse结构：
 * 1. 检查网络错误
 * 2. 解析JSON响应数据
 * 3. 根据API标准格式提取字段
 * 4. 处理成功和错误两种情况
 */
ApiClient::ApiResponse ApiClient::parseResponse(QNetworkReply *reply)
{
    // === 初始化响应结构 ===
    ApiResponse response;
    response.statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();

    // === 检查网络错误 ===
    if (reply->error() != QNetworkReply::NoError) {
        response.success = false;
        response.errorMessage = reply->errorString();
        response.errorCode = "NETWORK_ERROR";
        return response;
    }

    // === 读取响应数据 ===
    QByteArray data = reply->readAll();
    /* 示例原始响应数据（QByteArray）：
     * "{\"success\":true,\"data\":{\"token\":\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\"user\":{\"id\":123,\"username\":\"player123\",\"email\":\"player@example.com\"}},\"timestamp\":1640995200}"
     */

    // === 解析JSON数据 ===
    QJsonParseError parseError;
    QJsonDocument doc = QJsonDocument::fromJson(data, &parseError);

    // === 检查JSON解析错误 ===
    if (parseError.error != QJsonParseError::NoError) {
        response.success = false;
        response.errorMessage = "JSON解析错误: " + parseError.errorString();
        response.errorCode = "INVALID_JSON";
        return response;
    }

    // === 解析JSON对象 ===
    QJsonObject jsonObj = doc.object();

    // === 根据API标准响应格式解析 ===
    /* 根据后端API文档的统一响应格式：
     * 成功响应：
     * {
     *   "success": true,
     *   "data": { ... },
     *   "timestamp": 1703328615000,
     *   "service": "service_name"
     * }
     *
     * 错误响应：
     * {
     *   "success": false,
     *   "error": {
     *     "code": "ERROR_CODE",
     *     "message": "错误描述",
     *     "details": "详细错误信息"
     *   },
     *   "timestamp": 1703328615000,
     *   "service": "service_name"
     * }
     */
    response.success = jsonObj["success"].toBool();

    if (response.success) {
        // === 成功响应处理 ===
        if (jsonObj.contains("data")) {
            // 如果有data字段，使用data字段的内容
            response.data = jsonObj["data"].toObject();
        } else {
            // 如果没有data字段，使用整个响应对象（排除success字段）
            response.data = jsonObj;
            response.data.remove("success");  // 移除success字段避免混淆
        }
        response.timestamp = jsonObj["timestamp"].toVariant().toLongLong();
    } else {
        // === 错误响应处理 ===
        if (jsonObj.contains("error") && jsonObj["error"].isObject()) {
            // 新的统一错误格式
            QJsonObject errorObj = jsonObj["error"].toObject();
            response.errorCode = errorObj["code"].toString();
            response.errorMessage = errorObj["message"].toString();
        } else {
            // 兼容旧格式
            response.errorMessage = jsonObj["error_message"].toString();
            response.errorCode = jsonObj["error_code"].toString();
            // 如果还没有错误信息，尝试其他字段
            if (response.errorMessage.isEmpty()) {
                response.errorMessage = jsonObj["message"].toString();
            }
        }
        response.timestamp = jsonObj["timestamp"].toVariant().toLongLong();
    }

    return response;
}

/**
 * @brief 设置访问令牌
 * @param token JWT访问令牌
 *
 * 设置用于API认证的访问令牌，并自动保存到本地存储
 */
void ApiClient::setToken(const QString &token)
{
    m_accessToken = token;  // 更新内存中的令牌
    saveTokens();           // 保存到本地存储
}

/**
 * @brief 获取当前访问令牌
 * @return 当前的JWT访问令牌
 */
QString ApiClient::getToken() const
{
    return m_accessToken;
}

/**
 * @brief 设置刷新令牌
 * @param refreshToken JWT刷新令牌
 *
 * 设置用于自动刷新访问令牌的刷新令牌，并保存到本地存储
 */
void ApiClient::setRefreshToken(const QString &refreshToken)
{
    m_refreshToken = refreshToken;  // 更新内存中的刷新令牌
    saveTokens();                   // 保存到本地存储
}

/**
 * @brief 获取当前刷新令牌
 * @return 当前的JWT刷新令牌
 */
QString ApiClient::getRefreshToken() const
{
    return m_refreshToken;
}

/**
 * @brief 清除所有令牌
 *
 * 清除内存和本地存储中的所有认证令牌：
 * 1. 清空内存中的令牌变量
 * 2. 从QSettings中删除保存的令牌
 */
void ApiClient::clearTokens()
{
    // === 清空内存中的令牌 ===
    m_accessToken.clear();
    m_refreshToken.clear();

    // === 从本地存储中删除令牌 ===
    m_settings->remove("access_token");
    m_settings->remove("refresh_token");
}

/**
 * @brief 检查是否已认证
 * @return true表示已有有效的访问令牌，false表示未认证
 *
 * 通过检查访问令牌是否为空来判断认证状态
 */
bool ApiClient::isAuthenticated() const
{
    return !m_accessToken.isEmpty();
}

/**
 * @brief 设置请求超时时间
 * @param milliseconds 超时时间（毫秒）
 *
 * 设置网络请求的超时时间，超时后会自动取消请求
 */
void ApiClient::setTimeout(int milliseconds)
{
    m_timeout = milliseconds;
}

/**
 * @brief 设置重试次数
 * @param count 最大重试次数
 *
 * 设置网络请求失败时的最大重试次数
 */
void ApiClient::setRetryCount(int count)
{
    m_retryCount = count;
}

/**
 * @brief 刷新访问令牌
 *
 * 使用刷新令牌向服务器请求新的访问令牌：
 * 1. 构建包含刷新令牌的请求数据
 * 2. 创建不包含Authorization头的请求
 * 3. 发送POST请求到令牌刷新端点
 * 4. 连接响应处理槽函数
 */
void ApiClient::refreshAccessToken()
{
    // === 构建请求数据 ===
    QJsonObject data;
    data["refresh_token"] = m_refreshToken;
    /* 示例刷新令牌请求数据：
     * 输入：m_refreshToken = "refresh_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
     * 构建的JSON对象：
     * {
     *   "refresh_token": "refresh_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
     * }
     *
     * 序列化后的请求体：
     * "{\"refresh_token\":\"refresh_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\"}"
     */

    // === 创建请求对象 ===
    QNetworkRequest request = createRequest("/api/v1/auth/refresh");
    request.setRawHeader("Authorization", ""); // 清除Authorization头，使用刷新令牌认证

    // === 发送刷新请求 ===
    QJsonDocument doc(data);
    QNetworkReply *reply = m_networkManager->post(request, doc.toJson());

    // === 连接响应处理 ===
    connect(reply, &QNetworkReply::finished, this, &ApiClient::onRefreshTokenFinished);
}

/**
 * @brief 令牌刷新完成槽函数
 *
 * 处理令牌刷新请求的响应：
 * 1. 解析刷新响应
 * 2. 如果成功，更新访问令牌并重试待处理请求
 * 3. 如果失败，清除所有令牌并要求重新认证
 * 4. 清理响应对象和待处理请求队列
 */
void ApiClient::onRefreshTokenFinished()
{
    // === 获取响应对象 ===
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    if (!reply) return;

    // === 解析响应数据 ===
    ApiResponse response = parseResponse(reply);
    /* 示例令牌刷新响应：
     * 成功响应：
     * {
     *   "success": true,
     *   "data": {
     *     "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
     *     "expires_in": 3600
     *   },
     *   "timestamp": 1640995200
     * }
     *
     * 失败响应：
     * {
     *   "success": false,
     *   "error_message": "刷新令牌已过期",
     *   "error_code": "REFRESH_TOKEN_EXPIRED",
     *   "timestamp": 1640995200
     * }
     */

    if (response.success) {
        // === 刷新成功处理 ===
        QString newToken = response.data["token"].toString();
        /* 示例新令牌提取：
         * 从response.data["token"]提取：
         * "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
         */
        setToken(newToken);                 // 更新访问令牌
        emit tokenRefreshed(newToken);      // 发出令牌刷新成功信号

        qDebug() << "令牌刷新成功";

        // === 重试待处理的请求 ===
        // 使用新的访问令牌重新发送之前失败的请求
        for (const auto &pendingRequest : m_pendingRequests) {
            retryRequest(pendingRequest);
        }
        m_pendingRequests.clear();          // 清空待处理队列
    } else {
        // === 刷新失败处理 ===
        // 刷新令牌也无效，需要用户重新登录
        clearTokens();                      // 清除所有令牌
        emit authenticationRequired();      // 发出需要重新认证信号
        m_pendingRequests.clear();          // 清空待处理队列
    }

    // === 清理响应对象 ===
    reply->deleteLater();
}

/**
 * @brief 重试请求
 * @param request 待重试的请求信息
 *
 * 根据请求的HTTP方法重新发送请求：
 * - 使用新刷新的访问令牌
 * - 保持原有的端点和数据
 * - 支持GET、POST、PUT、DELETE方法
 */
void ApiClient::retryRequest(const PendingRequest &request)
{
    // === 根据HTTP方法重新发送请求 ===
    if (request.method == "GET") {
        get(request.endpoint, request.data);
    } else if (request.method == "POST") {
        post(request.endpoint, request.data);
    } else if (request.method == "PUT") {
        put(request.endpoint, request.data);
    } else if (request.method == "DELETE") {
        del(request.endpoint);
    }
}

/**
 * @brief 保存令牌到本地存储
 *
 * 将访问令牌和刷新令牌保存到QSettings，
 * 以便应用程序重启后能够恢复认证状态
 */
void ApiClient::saveTokens()
{
    /* 示例令牌保存过程：
     * 输入令牌：
     * m_accessToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
     * m_refreshToken = "refresh_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
     *
     * 保存到QSettings（Windows注册表/Linux配置文件）：
     * [QtGameClient]
     * access_token="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
     * refresh_token="refresh_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
     */
    m_settings->setValue("access_token", m_accessToken);
    m_settings->setValue("refresh_token", m_refreshToken);
}

/**
 * @brief 从本地存储加载令牌
 *
 * 从QSettings加载保存的令牌信息，
 * 在应用程序启动时恢复认证状态
 */
void ApiClient::loadTokens()
{
    /* 示例令牌加载过程：
     * 从QSettings读取：
     * access_token="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
     * refresh_token="refresh_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
     *
     * 加载到内存变量：
     * m_accessToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
     * m_refreshToken = "refresh_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
     *
     * 如果没有保存的令牌，返回空字符串
     */
    m_accessToken = m_settings->value("access_token").toString();
    m_refreshToken = m_settings->value("refresh_token").toString();
}
